<script lang="ts">
  export default { name: 'ChannelForm' };
</script>

<script setup lang="ts">
  import { ref, computed, toRefs, watch, PropType } from 'vue';
  import { toTree, disableSubtree, disableTreeWithPermission } from '@/utils/tree';
  import {
    queryChannel,
    createChannel,
    updateChannel,
    deleteChannel,
    queryChannelList,
    queryChannelPermissions,
    queryChannelTemplates,
    queryArticleTemplates,
    channelAliasExist,
  } from '@/api/content';
  import { queryProcessDefinitionList } from '@/api/system';
  import { queryModelList } from '@/api/config';
  import { getModelData, mergeModelFields, arr2obj } from '@/data';
  import { currentUser } from '@/store/useCurrentUser';
  import FieldItem from '@/views/config/components/FieldItem.vue';
  import DialogForm from '@/components/DialogForm.vue';
  import LabelTip from '@/components/LabelTip.vue';
  import Tinymce from '@/components/Tinymce';
  import { TuiEditor } from '@/components/TuiEditor';
  import { ImageUpload } from '@/components/Upload';

  const props = defineProps({
    modelValue: { type: Boolean, required: true },
    beanId: { type: Number, default: null },
    beanIds: { type: Array as PropType<number[]>, required: true },
    parent: { type: Object, default: null },
  });
  const emit = defineEmits({ 'update:modelValue': null, finished: null });

  const { modelValue: visible, parent } = toRefs(props);
  const focus = ref < any > ();
  const values = ref < any > ({});
  const processList = ref < any[] > ([]);
  const channelList = ref < any[] > ([]);
  const channelModelList = ref < any[] > ([]);
  const articleModelList = ref < any[] > ([]);
  const channelPermissions = ref < number[] > ([]);
  const channelTemplates = ref < any[] > ([]);
  const articleTemplates = ref < any[] > ([]);
  const channelModelId = ref < number > ();
  const channelModel = computed(() => channelModelList.value.find((item) => item.id === channelModelId.value));
  const mains = computed(() => arr2obj(mergeModelFields(getModelData().channel.mains, channelModel.value?.mains, 'channel')));
  const asides = computed(() => arr2obj(mergeModelFields(getModelData().channel.asides, channelModel.value?.asides, 'channel')));
  const fields = computed(() => JSON.parse(channelModel.value?.customs || '[]'));
  const parentChannelList = computed(() => {
    const list = disableSubtree(channelList.value, values.value.id);
    if (!currentUser.allChannelPermission) {
      return disableTreeWithPermission(list, channelPermissions.value);
    }
    return list;
  });

  const fetchChannelList = async () => {
    channelList.value = toTree(await queryChannelList());
  };
  const fetchProcessList = async () => {
    if (currentUser.epRank > 0) {
      processList.value = await queryProcessDefinitionList({ category: 'sys_article', latestVersion: true });
    }
  };
  const finished = async () => {
    await fetchChannelList();
    emit('finished');
  };
  const fetchChannelModelList = async () => {
    channelModelList.value = await queryModelList({ type: 'channel' });
    // 如果 channelModelId 无值，则默认赋予第一个模型的值
    if (channelModelId.value == null && channelModelList.value.length > 0) {
      channelModelId.value = channelModelList.value[0].id;
    }
  };
  const fetchArticleModelList = async () => {
    articleModelList.value = await queryModelList({ type: 'article' });
  };
  const fetchChannelTemplates = async () => {
    channelTemplates.value = await queryChannelTemplates();
  };
  const fetchArticleTemplates = async () => {
    articleTemplates.value = await queryArticleTemplates();
  };
  const fetchChannelPermissions = async () => {
    channelPermissions.value = await queryChannelPermissions();
  };
  watch(visible, () => {
    if (visible.value) {
      channelModelId.value = parent.value?.articleModelId ?? channelModelList.value[0]?.id;
      fetchChannelPermissions();
      fetchChannelModelList();
      fetchArticleModelList();
      fetchChannelTemplates();
      fetchArticleTemplates();
      fetchChannelList();
      fetchProcessList();
    }
  });
  watch(fields, () => {
    initCustoms(values.value.customs);
  });
  const initCustoms = (customs: any) => {
    fields.value.forEach((field: any) => {
      if (customs[field.code] == null) {
        customs[field.code] = field.defaultValue;
        if (field.defaultValueKey != null) {
          customs[field.code + '_key'] = field.defaultValueKey;
        }
      }
    });
    return customs;
  };
</script>

<template>
  <dialog-form style="margin:auto;width: 40%;margin-top:100px" v-model:values="values" :name="$t('menu.content.channel')"
    :query-bean="queryChannel" :create-bean="createChannel" :update-bean="updateChannel" :delete-bean="deleteChannel"
    :bean-id="beanId" :bean-ids="beanIds" :focus="focus" :init-values="(bean: any): any => ({
      parentId: bean?.parentId ?? parent?.id,
      type: 1,
      channelModelId: bean?.channelModelId ?? parent?.channelModelId ?? channelModelList[0]?.id,
      articleModelId: bean?.articleModelId ?? parent?.articleModelId ?? articleModelList[0]?.id,
      nav: bean?.nav ?? parent?.nav ?? true,
      channelTemplate: bean?.channelTemplate ?? parent?.channelTemplate ?? channelTemplates[0],
      articleTemplate: bean?.articleTemplate ?? parent?.articleTemplate ?? articleTemplates[0],
      pageSize: 20,
      allowComment: bean?.allowComment ?? parent?.allowComment ?? true,
      allowContribute: bean?.allowContribute ?? parent?.allowContribute ?? true,
      allowSearch: bean?.allowSearch ?? parent?.allowSearch ?? true,
      customs: {},
    })" :to-values="(bean) => ({ ...bean })" perms="channel" :model-value="modelValue"
    :disable-edit="(bean) => !currentUser.allChannelPermission && bean.id != null && !channelPermissions.includes(bean.id)"
    label-width="120px" large @update:model-value="(event) => $emit('update:modelValue', event)" @finished="finished"
    @bean-change="
      (bean) => {
        channelModelId = bean?.channelModelId ?? parent?.channelModelId ?? articleModelList[0]?.id;
        fetchChannelList();
      }
    ">
    <template #default="{ bean }">
      <el-row>
        <el-col :span="14">
          <el-row>
            <el-col :span="mains['name'].double ? 24 : 24">
              <el-form-item prop="name" :label="mains['name'].name ?? $t('channel.name')"
                :rules="{ required: true, message: () => $t('v.required') }">
                <el-input ref="focus" v-model="values.name" maxlength="50"></el-input>
              </el-form-item>
            </el-col>
            <el-col :span="mains['alias'].double ? 24 : 24">
              <el-form-item prop="alias" :rules="[
                  { required: true, message: () => $t('v.required') },
                  { pattern: /^[\w-]*$/, message: () => $t('channel.error.aliasPattern') },
                  {
                    asyncValidator: async (rule, value, callback) => {
                      if (value !== bean.alias && (await channelAliasExist(value))) {
                        callback($t('channel.error.aliasExist'));
                        return;
                      }
                      callback();
                    },
                  },
                ]">
                <template #label><label-tip :label="mains['alias'].name ?? $t('channel.alias')" message="channel.alias"
                    help /></template>
                <el-input v-model="values.alias" maxlength="50"></el-input>
              </el-form-item>
            </el-col>
            <el-col v-if="values.type === 3" :span="mains['linkUrl'].double ? 24 : 24">
              <el-form-item prop="linkUrl" :rules="[
                  { required: true, message: () => $t('v.required') },
                  { pattern: /^(http|\/).*$/, message: () => $t('channel.error.linkUrl') },
                ]">
                <template #label><label-tip :label="mains['linkUrl'].name ?? $t('channel.linkUrl')"
                    message="channel.linkUrl" help /></template>
                <el-input v-model="values.linkUrl" maxlength="255">
                  <template #append>
                    <el-checkbox v-model="values.targetBlank">{{ $t('channel.targetBlank') }}</el-checkbox>
                  </template>
                </el-input>
              </el-form-item>
            </el-col>
            <!-- <template v-if="values.type < 3">
              <el-col v-if="mains['seoTitle'].show" :span="mains['seoTitle'].double ? 24 : 24">
                <el-form-item
                  prop="seoTitle"
                  :label="mains['seoTitle'].name ?? $t('channel.seoTitle')"
                  :rules="mains['seoTitle'].required ? { required: true, message: () => $t('v.required') } : undefined"
                >
                  <el-input v-model="values.seoTitle" maxlength="150"></el-input>
                </el-form-item>
              </el-col>
              <el-col v-if="mains['seoKeywords'].show" :span="mains['seoKeywords'].double ? 24 : 24">
                <el-form-item
                  prop="seoKeywords"
                  :label="mains['seoKeywords'].name ?? $t('channel.seoKeywords')"
                  :rules="mains['seoKeywords'].required ? { required: true, message: () => $t('v.required') } : undefined"
                >
                  <el-input v-model="values.seoKeywords" maxlength="150"></el-input>
                </el-form-item>
              </el-col>
              <el-col v-if="mains['seoDescription'].show" :span="mains['seoDescription'].double ? 24 : 24">
                <el-form-item
                  prop="seoDescription"
                  :label="mains['seoDescription'].name ?? $t('channel.seoDescription')"
                  :rules="mains['seoDescription'].required ? { required: true, message: () => $t('v.required') } : undefined"
                >
                  <el-input v-model="values.seoDescription" maxlength="1000"></el-input>
                </el-form-item>
              </el-col>
            </template> -->
            <el-col v-if="mains['image'].show" :span="mains['image'].double ? 24 : 24">
              <el-form-item prop="image" :label="mains['image'].name ?? $t('channel.image')"
                :rules="mains['image'].required ? { required: true, message: () => $t('v.required') } : undefined">
                <image-upload v-model="values.image" :height="mains['image'].imageHeight"
                  :width="mains['image'].imageWidth" :mode="mains['image'].imageMode"></image-upload>
              </el-form-item>
            </el-col>
            <el-col v-if="mains['channelModel'].show" :span="mains['channelModel'].double ? 24 : 24">
              <el-form-item prop="channelModelId" :label="mains['channelModel'].name ?? $t('channel.channelModel')"
                :rules="{ required: true, message: () => $t('v.required') }">
                <el-select v-model="values.channelModelId" class="w-full" @change="
                    (value) => {
                      channelModelId = value;
                    }
                  ">
                  <el-option v-for="item in channelModelList" :key="item.id" :label="item.name"
                    :value="item.id"></el-option>
                </el-select>
              </el-form-item>
            </el-col>
            <el-col v-if="mains['articleModel'].show" :span="mains['articleModel'].double ? 24 : 24">
              <el-form-item prop="articleModelId" :label="mains['articleModel'].name ?? $t('channel.articleModel')"
                :rules="{ required: true, message: () => $t('v.required') }">
                <el-select v-model="values.articleModelId" class="w-full">
                  <el-option v-for="item in articleModelList" :key="item.id" :label="item.name"
                    :value="item.id"></el-option>
                </el-select>
              </el-form-item>
            </el-col>
            <!-- <template v-if="![3, 4, 5].includes(values.type)">
              <el-col v-if="mains['channelTemplate'].show" :span="mains['channelTemplate'].double ? 24 : 24">
                <el-form-item
                  prop="channelTemplate"
                  :label="mains['channelTemplate'].name ?? $t('channel.channelTemplate')"
                  :rules="mains['channelTemplate'].required ? { required: true, message: () => $t('v.required') } : undefined"
                >
                  <el-select v-model="values.channelTemplate" class="w-full">
                    <el-option v-for="item in channelTemplates" :key="item" :label="item + '.html'" :value="item"></el-option>
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col v-if="mains['articleTemplate'].show" :span="mains['articleTemplate'].double ? 24 : 24">
                <el-form-item
                  prop="articleTemplate"
                  :label="mains['articleTemplate'].name ?? $t('channel.articleTemplate')"
                  :rules="mains['articleTemplate'].required ? { required: true, message: () => $t('v.required') } : undefined"
                >
                  <el-select v-model="values.articleTemplate" class="w-full">
                    <el-option v-for="item in articleTemplates" :key="item" :label="item + '.html'" :value="item"></el-option>
                  </el-select>
                </el-form-item>
              </el-col>
            </template> -->
            <!-- <el-col v-if="mains['allowComment'].show" :span="mains['allowComment'].double ? 24 : 24">
              <el-form-item
                prop="allowComment"
                :label="mains['allowComment'].name ?? $t('channel.allowComment')"
                :rules="mains['allowComment'].required ? { required: true, message: () => $t('v.required') } : undefined"
              >
                <el-switch v-model="values.allowComment"></el-switch>
              </el-form-item>
            </el-col> -->
            <!-- <el-col v-if="mains['allowContribute'].show" :span="mains['allowContribute'].double ? 24 : 24">
              <el-form-item
                prop="allowContribute"
                :label="mains['allowContribute'].name ?? $t('channel.allowContribute')"
                :rules="mains['allowContribute'].required ? { required: true, message: () => $t('v.required') } : undefined"
              >
                <el-switch v-model="values.allowContribute"></el-switch>
              </el-form-item>
            </el-col> -->
            <!-- <el-col v-if="mains['nav'].show" :span="mains['nav'].double ? 24 : 24">
              <el-form-item prop="nav" :rules="mains['nav'].required ? { required: true, message: () => $t('v.required') } : undefined">
                <template #label><label-tip :label="mains['nav'].name ?? $t('channel.nav')" message="channel.nav" help /></template>
                <el-switch v-model="values.nav"></el-switch>
              </el-form-item>
            </el-col> -->
            <!-- <el-col v-if="mains['allowSearch'].show" :span="mains['allowSearch'].double ? 24 : 24">
              <el-form-item
                prop="allowSearch"
                :label="mains['allowSearch'].name ?? $t('channel.allowSearch')"
                :rules="mains['allowSearch'].required ? { required: true, message: () => $t('v.required') } : undefined"
              >
                <el-switch v-model="values.allowSearch"></el-switch>
              </el-form-item>
            </el-col> -->
            <template v-for="field in fields" :key="field.code">
              <el-col :span="field.double ? 24 : 24">
                <el-form-item :prop="`customs.${field.code}`"
                  :rules="field.required ? { required: true, message: () => $t('v.required') } : undefined">
                  <template #label><label-tip :label="field.name" /></template>
                  <field-item v-model="values.customs[field.code]"
                    v-model:model-key="values.customs[field.code + '_key']" :field="field"></field-item>
                </el-form-item>
              </el-col>
            </template>
            <!-- <el-col v-if="values.type === 2" :span="mains['text'].double ? 24 : 24">
              <el-form-item prop="text" :label="mains['text'].name ?? $t('channel.text')"
                :rules="mains['text'].required ? { required: true, message: () => $t('v.required') } : undefined">
                <div class="w-full">
                  <el-radio-group v-if="mains['text'].editorSwitch" v-model="values.editorType" class="mr-6"
                    @change="() => (values.markdown = '')">
                    <el-radio v-for="n in [1, 2]" :key="n" :label="n">{{ $t(`model.field.editorType.${n}`) }}</el-radio>
                  </el-radio-group>
                  <tui-editor v-if="values.editorType === 2" v-model="values.markdown" v-model:html="values.text"
                    class="leading-6" />
                  <tinymce v-else ref="tinyText" v-model="values.text" />
                </div>
              </el-form-item>
            </el-col> -->
          </el-row>
        </el-col>
        <el-col :span="10" class="el-form--label-top label-top">
          <el-tabs type="border-card" class="ml-5">
            <el-tab-pane :label="$t('channel.tabs.setting')">
              <el-form-item prop="parentId" :label="asides['parent'].name ?? $t('channel.parent')">
                <el-tree-select v-model="values.parentId" :data="parentChannelList" node-key="id"
                  :props="{ label: 'name', disabled: 'disabled' }" :render-after-expand="false" check-strictly clearable
                  class="w-full" />
              </el-form-item>
              <!-- <el-form-item prop="type" :label="asides['type'].name ?? $t('channel.type')" :rules="{ required: true, message: () => $t('v.required') }">
                <el-select v-model="values.type" class="w-full">
                  <el-option v-for="n in [1, 2, 3, 4]" :key="n" :label="$t(`channel.type.${n}`)" :value="n"></el-option>
                </el-select>
              </el-form-item> -->
              <!-- <el-form-item
                prop="processKey"
                :label="asides['processKey'].name ?? $t('channel.processKey')"
                :rules="asides['processKey'].required ? { required: true, message: () => $t('v.required') } : undefined"
              >
                <el-select v-model="values.processKey" clearable class="w-full">
                  <el-option v-for="item in processList" :key="item.key" :label="item.name" :value="item.key"></el-option>
                </el-select>
              </el-form-item> -->
              <!-- <el-form-item prop="pageSize" :label="asides['pageSize'].name ?? $t('channel.pageSize')" :rules="{ required: true, message: () => $t('v.required') }">
                <el-input-number v-model="values.pageSize" :min="1" :max="200"></el-input-number>
              </el-form-item> -->
            </el-tab-pane>
          </el-tabs>
        </el-col>
      </el-row>
    </template>
  </dialog-form>
</template>

<style lang="scss" scoped>
  .label-top {
    :deep(.el-form-item) {
      margin-bottom: 12px;
    }

    :deep(.el-form-item__label) {
      margin-bottom: 4px;
      width: 100% !important;
    }
  }
</style>
